package inutan.match.service;

import bright.serialization.ByteBuf;
import inutan.common.constant.DataConstant;
import inutan.common.context.FlowContext;
import inutan.match.GroupRoom;
import inutan.match.UserBaseInfo;
import luban.common.Command;
import luban.room.ChangeRoomUserState;
import luban.room.CreateOrEnterRoom;
import luban.room.RoomType;
import luban.room.RoomUserInfo;
import org.ricks.common.lang.Logger;
import org.ricks.ioc.anno.Bean;
import org.ricks.net.DefaultPacket;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：demon-chen
 * 来自业务集群的消息 使用自定义消息体
 * 如果1:1 对应 ，
 */
@Bean
public class MatchService {

    /**
     * key -> 房间类型
     */
    private static final Map<Integer, GroupRoom> groupRoomMap = new ConcurrentHashMap<>();

    /**
     * 玩家登录，业务服同步基础信息到匹配服
     * 进入MMO房间
     * 进入聊天房间
     * @param context
     */
    public void loginMatch(FlowContext<DefaultPacket> context) {
        RoomUserInfo userInfo = RoomUserInfo.deserializeRoomUserInfo(new ByteBuf(context.getPacket().getPacket()));

//        UserBaseInfo userBaseInfo = new UserBaseInfo(context.getUserId(), userInfo.userName, userInfo.level, userInfo.sex, userInfo.icon);

        /**
         * 匹配服维护基础信息
         */
        UserBaseInfo userBaseInfo = new UserBaseInfo(1, "ricks",1,1,1);
        /**
         * 进入MMO房间
         */
        enterRoom(context, userBaseInfo, RoomType.MmoRoom);
        /**
         * 进入聊天房间
         */
        enterRoom(context, userBaseInfo, RoomType.ChatRoom);
    }

    public String genGroupId(int roomType,long roomId) {
        StringBuilder builder = new StringBuilder(roomType);
        builder.append("-");
        builder.append(roomId);
        return builder.toString();
    }

    /**
     * 主动创建房间，跨服小游戏
     * @param context
     */
    public void createRoom(FlowContext<DefaultPacket> context) {
        CreateOrEnterRoom createOrEnterRoom = CreateOrEnterRoom.deserializeCreateOrEnterRoom(new ByteBuf(context.getPacket().getPacket()));
        int roomEnum = createOrEnterRoom.roomType;
        Logger.info(context.getUserId() + ": 创建房间 ，roomType:" + roomEnum);
        UserBaseInfo userBaseInfo = new UserBaseInfo(context.getUserId(), createOrEnterRoom.userInfo.userName, createOrEnterRoom.userInfo.level, createOrEnterRoom.userInfo.sex, createOrEnterRoom.userInfo.icon);

        enterRoom(context, userBaseInfo, roomEnum);
    }

    /**
     * 进入或创建 房间
     * 房间匹配逻辑，比如MMO没有所谓的创建 登录的时换默认分配房间 如果不存在MMO房间则创建，房间满了则创建
     * 聊天同样，小游戏则可以主动创建房间
     * 聊天房间 和 mmo房间 玩家没有主动创建权限
     *
     * 1.分配房间
     * 2.玩家进入房间，通知这个房间其它玩家。A进入了房间
     * @param context
     */
    public void enterRoom(FlowContext<DefaultPacket> context) {
        CreateOrEnterRoom createOrEnterRoom = CreateOrEnterRoom.deserializeCreateOrEnterRoom(new ByteBuf(context.getPacket().getPacket()));
        int roomEnum = createOrEnterRoom.roomType;
        Logger.info(context.getUserId() + ": 进入房间 ，roomType:" + roomEnum);
        UserBaseInfo userBaseInfo = new UserBaseInfo(context.getUserId(), createOrEnterRoom.userInfo.userName, createOrEnterRoom.userInfo.level, createOrEnterRoom.userInfo.sex, createOrEnterRoom.userInfo.icon);
        enterRoom(context, userBaseInfo, roomEnum);
    }

    public void enterRoom(FlowContext context, UserBaseInfo userBaseInfo, int roomType) {
        Logger.info(context.getUserId() + ": 进入房间 ，roomType:" + roomType);
        GroupRoom groupRoom = groupRoomMap.computeIfAbsent(roomType,  k -> new GroupRoom(roomType));
        long roomId = groupRoom.createRoomId();
        //相同房间类型 只能允许玩家在一个房间中。创建房间之前先退出之前房间
        groupRoom.remove(context.getUserId());
        groupRoom.join(roomId, userBaseInfo);
        ChangeRoomUserState changeRoomUserState = new ChangeRoomUserState();
        changeRoomUserState.roomId = roomType +"-" +roomId;
        changeRoomUserState.isBind = true;
        context.sendResponse(DataConstant.RUTE_MESSAGE, Command.ChangeRoomUserState, changeRoomUserState); //路由网关绑定关系
        context.sendResponse(DataConstant.BROADCAST_MESSAGE,Command.EnterRoom,new CreateOrEnterRoom());
    }


    /**
     * 玩家退出房间，通知这个房间其它玩家。A退出了房间
     * @param context
     * @param roomType
     * @param roomId
     */
    public void exitRoom(FlowContext context,int roomType,long roomId) {
        GroupRoom groupRoom = groupRoomMap.computeIfAbsent(roomType,  k -> new GroupRoom(roomType));
        groupRoom.remove(roomId, context.getUserId());
        context.sendResponse(DataConstant.RUTE_MESSAGE,Command.ExitRoom); //路由网关解除绑定关系
    }
}
